Skip to main content

Overview

The fetch_corporate_actions.py script retrieves corporate action events in two time scenarios: historical events (past 2 years) and upcoming events (next 2 months). This dual-fetch approach enables both historical analysis and future event tracking.

Purpose

Fetches corporate action data including:
  • Dividends - Cash dividend announcements
  • Bonuses - Bonus share issues
  • Stock Splits - Share split events
  • Rights Issues - Rights offering announcements
  • Quarterly Results - Result announcement dates
  • Buybacks - Share buyback programs

API Endpoint

URL
string
required
https://ow-scanx-analytics.dhan.co/customscan/fetchdt
Method
string
required
POST

Request Payload

{
  "data": {
    "type": "full",
    "whichpage": "corporate_action",
    "filters": [
      {"field": "CorpAct.ActDate", "op": "GT", "val": "<DATE>"}
    ],
    "count": 5000,
    "page": 1
  }
}

Parameters

data.sort
string
default:"CorpAct.ExDate"
Field to sort by (Ex-Date)
data.sorder
string
default:"asc"
Sort order (asc for chronological, desc for reverse)
data.count
number
default:"5000"
Maximum number of records to fetch
data.fields
array
Fields to retrieve:
  • CorpAct.ActType - Action type (DIVIDEND, BONUS, etc.)
  • Sym - Stock symbol
  • DispSym - Display name
  • CorpAct.ExDate - Ex-date
  • CorpAct.RecDate - Record date
  • CorpAct.Note - Details (e.g., “Rs 10 per share”)
data.params
array
Filter parameters:
  • {"field": "Seg", "op": "", "val": "E"} - Equity segment
  • {"field": "OgInst", "op": "", "val": "ES"} - Equity stocks
  • {"field": "CorpAct.ExDate", "op": "lte", "val": "<END_DATE>"} - Date range (end)
  • {"field": "CorpAct.ExDate", "op": "gte", "val": "<START_DATE>"} - Date range (start)
  • {"field": "Mcapclass", "op": "", "val": "Largecap,Midcap,Smallcap,Microcap"} - All cap sizes
  • {"field": "CorpAct.ActType", "op": "", "val": "BONUS,DIVIDEND,QUARTERLY RESULT ANNOUNCEMENT,SPLIT,RIGHTS,BUYBACK"} - Action types

Output Files

history_corporate_actions.json
array
Historical corporate actions from past 2 years. Each object contains:
{
  "Symbol": "RELIANCE",
  "Name": "Reliance Industries Ltd.",
  "Type": "DIVIDEND",
  "ExDate": "2024-01-15",
  "RecordDate": "2024-01-16",
  "Details": "Rs 10 per share"
}
Sorted by ExDate (ascending).
upcoming_corporate_actions.json
array
Upcoming corporate actions for next 2 months. Same structure as historical data.

Function Signature

def fetch_corporate_actions_scenarios():
    """
    Fetches corporate actions in two time scenarios:
    1. Historical: Past 2 years up to yesterday
    2. Upcoming: Today onwards for 2 months
    
    Returns:
        None (writes to history_corporate_actions.json and upcoming_corporate_actions.json)
        
    Process:
        1. Calculate date ranges (IST timezone)
        2. Fetch historical actions (2 years ago to yesterday)
        3. Fetch upcoming actions (today to +2 months)
        4. Flatten nested CorpAct arrays
        5. Filter strictly by date range
        6. Sort by ExDate
        7. Save to separate JSON files
    """

Dependencies

Python Packages
list
  • requests - HTTP client
  • json - JSON processing
  • datetime, timedelta - Date calculations (IST timezone)
  • os - File operations
Local Modules
list
  • pipeline_utils.get_headers() - Returns API headers with Origin header
Input Files
list
None - Fetches data directly from API

Code Example

import requests
import json
from datetime import datetime, timedelta
from pipeline_utils import get_headers

def fetch_corporate_actions_scenarios():
    url = "https://ow-scanx-analytics.dhan.co/customscan/fetchdt"
    
    # Calculate dates in IST (UTC +5:30)
    utc_now = datetime.utcnow()
    ist_now = utc_now + timedelta(hours=5, minutes=30)
    today_str = ist_now.strftime("%Y-%m-%d")
    two_years_ago = (ist_now - timedelta(days=365 * 2)).strftime("%Y-%m-%d")
    two_months_forward = (ist_now + timedelta(days=60)).strftime("%Y-%m-%d")

    headers = get_headers(include_origin=True)

    common_fields = ["CorpAct.ActType", "Sym", "DispSym", "CorpAct.ExDate", "CorpAct.RecDate", "CorpAct.Note"]
    
    def get_data(start_date, end_date):
        payload = {
            "data": {
                "sort": "CorpAct.ExDate",
                "sorder": "asc",
                "count": 5000,
                "fields": common_fields,
                "params": [
                    {"field": "Seg", "op": "", "val": "E"},
                    {"field": "OgInst", "op": "", "val": "ES"},
                    {"field": "CorpAct.ExDate", "op": "lte", "val": end_date},
                    {"field": "CorpAct.ExDate", "op": "gte", "val": start_date},
                    {"field": "Mcapclass", "op": "", "val": "Largecap,Midcap,Smallcap,Microcap"},
                    {"field": "CorpAct.ActType", "op": "", "val": "BONUS,DIVIDEND,QUARTERLY RESULT ANNOUNCEMENT,SPLIT,RIGHTS,BUYBACK"}
                ],
                "pgno": 0
            }
        }
        resp = requests.post(url, json=payload, headers=headers)
        resp.raise_for_status()
        raw_data = resp.json().get('data', [])
        
        # Flatten nested CorpAct array
        flattened = []
        for stock in raw_data:
            symbol = stock.get('Sym')
            name = stock.get('DispSym')
            actions = stock.get('CorpAct', [])
            for action in actions:
                ex_date = action.get('ExDate')
                # Strict date filtering
                if start_date <= ex_date <= end_date:
                    flattened.append({
                        "Symbol": symbol,
                        "Name": name,
                        "Type": action.get('ActType'),
                        "ExDate": ex_date,
                        "RecordDate": action.get('RecDate'),
                        "Details": action.get('Note')
                    })
        return sorted(flattened, key=lambda x: x['ExDate'])

    # Scenario 1: Historical
    print(f"Fetching Historical Data ({two_years_ago} to Yesterday)...")
    yesterday = (ist_now - timedelta(days=1)).strftime("%Y-%m-%d")
    history = get_data(two_years_ago, yesterday)
    with open("history_corporate_actions.json", "w") as f:
        json.dump(history, f, indent=4)
    print(f"Saved {len(history)} historical actions")

    # Scenario 2: Upcoming
    print(f"Fetching Upcoming Data (Today to +2 months)...")
    upcoming = get_data(today_str, two_months_forward)
    with open("upcoming_corporate_actions.json", "w") as f:
        json.dump(upcoming, f, indent=4)
    print(f"Saved {len(upcoming)} upcoming actions")

Usage

python3 fetch_corporate_actions.py

Performance

  • Execution Time: ~5-10 seconds
  • API Calls: 2 requests (one for historical, one for upcoming)
  • Output Size: Variable (depends on number of events)
  • Concurrency: Sequential (no threading)

Date Ranges

Historical Scenario

  • Start: 2 years before today (IST)
  • End: Yesterday (IST)
  • Purpose: Analyze past corporate actions and their market impact

Upcoming Scenario

  • Start: Today (IST)
  • End: 2 months ahead (IST)
  • Purpose: Track upcoming events for event-driven trading strategies

Data Flattening

The API returns nested structures with CorpAct arrays:
{
  "Sym": "RELIANCE",
  "CorpAct": [
    {"ActType": "DIVIDEND", "ExDate": "2024-01-15", ...},
    {"ActType": "BONUS", "ExDate": "2024-03-20", ...}
  ]
}
The script flattens this into individual action objects for easier processing.

Notes

  • Uses IST timezone (UTC +5:30) for all date calculations
  • Strict date filtering ensures no leakage between historical and upcoming datasets
  • Filters by market cap classes (Largecap, Midcap, Smallcap, Microcap)
  • Action types: BONUS, DIVIDEND, QUARTERLY RESULT ANNOUNCEMENT, SPLIT, RIGHTS, BUYBACK
  • Results are sorted chronologically by Ex-Date